package forestsimulatorp3.model.beings;

import forestsimulatorp3.model.beings.abstrakt.Animal;
import forestsimulatorp3.model.beings.abstrakt.LivingBeing;
import java.util.HashSet;
import java.util.Set;
import model.enums.Movement;
import forestsimulatorp3.model.position.Area;
import forestsimulatorp3.model.position.Square;
import forestsimulatorp3.model.simulator.Logger;

/**
 * Represents the forest.
 * @author dielson
 *
 */
public class Forest implements Environment {
    // Constants ---------------------------------------------------------------

    private final int X_SIZE = 100;
    private final int Y_SIZE = 100;
    // Attributes --------------------------------------------------------------
    private Set<LivingBeing> livingBeings;
    private int idCounter;
    private Area area;
    private Logger logger;

    // Constructors ------------------------------------------------------------
    public Forest() {
        livingBeings = new HashSet<LivingBeing>();
        idCounter = 0;
        area = new Area(X_SIZE, Y_SIZE);
    }

    // Public methods ----------------------------------------------------------

    @Override
    public Square moveTo(Square from, Square to) {
        for (LivingBeing being : livingBeings) {
            if (being.getPosition().equals(to)) {
                return from;
            }
        }
        if (area.addOccupiedPosition(to)) {
            area.removePosition(from);
            return to;
        }
        return from;
    }
    
    // Private methods ---------------------------------------------------------
    /**
     * Executes all the actions an animal can do on the forest on a cycle
     */
    private void executeActions(LivingBeing being) {
        // TODO: all livingbeing actions
        being.rest();

        if (being instanceof Animal) {
            executeAnimalActions((Animal) being);
        }
    }

    private void executeAnimalActions(Animal animal) {
        //TODO: all animal actions
        animal.move(Movement.randomSide());
    }

    // Implements Environment --------------------------------------------------

    @Override
    public int getNextAvailableId() {
        return idCounter++;
    }

    @Override
    public boolean removeLivingBeing(LivingBeing being) {
        return livingBeings.remove(being);
    }

    @Override
    public boolean addLivingBeing(LivingBeing being) {
        boolean added = livingBeings.add(being);
        if (added) {
            area.addOccupiedPosition(being.getPosition());
        }
        return added;
    }

    @Override
    public Logger getLogger() {
        return logger;
    }

    @Override
    public void setLogger(Logger logger) {
        this.logger = logger;
    }

    @Override
    public Area getArea() {
        return area;
    }

    @Override
    public void setArea(Area area) {
        this.area = area;
    }

    @Override
    public void advanceCycle() {
        for (LivingBeing being : livingBeings) {
            executeActions(being);
        }
    }

    @Override
    public Set<LivingBeing> getLivingBeings() {
        return livingBeings;
    }

    @Override
    public void setLivingBeings(Set<LivingBeing> livingBeings) {
        this.livingBeings = livingBeings;
        for (LivingBeing being : livingBeings) {
            area.addOccupiedPosition(being.getPosition());
        }
    }
}
